﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading;
using SteamFluentAPI.Infrastructure;
using SteamFluentAPI.Infrastructure.Base;

namespace SteamFluentAPI.Infrastructure
{
    public class SteamRequest
    {
        private string baseUrl;
        public string APIKey { get; set; }
        public SteamRequestFormat SteamRequestFormat { get; set; }
        public SteamGameType SteamGameType { get; set; }
        public string InterfaceName { get; set; }
        public string MethodName { get; set; }
        public bool HasRequiredParameters { get; set; }
        public List<string> RequiredParameters { get; set; }
        public SteamMethod SteamMethod { get; set; }
        public string VersionCode { get; set; }
        public Dictionary<string, object> Parameters { get; set; }

        public SteamRequest(string apikey, SteamRequestFormat format)
        {
            baseUrl = @"http://api.steampowered.com";
            APIKey = apikey;
            SteamGameType = SteamGameType.None;
            SteamRequestFormat = format;
            Parameters = new Dictionary<string, object>();
            RequiredParameters = new List<string>();
        }

        /// <summary>
        /// Retrieves the final SteamRequest.
        /// </summary>
        /// <returns></returns>
        public string GetRequest(int numberOfRetries)
        {
            string request = "";
            if (numberOfRetries > 0)
            {
                using (WebClient client = new WebClient())
                {
                    try
                    {
                        request = client.DownloadString(this.GetRequestString());
                    }
                    catch (ApplicationException ex)
                    {
                        throw ex;
                    }
                    catch (WebException)
                    {
                        Thread.Sleep(500);
                        GetRequest(numberOfRetries - 1);
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }
            }

            if (string.IsNullOrEmpty(request))
            {
                throw new ApplicationException("The remote server returned an error: (404) Not Found.");
            }

            return request;
        }

        /// <summary>
        /// Retrieves the constructed request URL.
        /// </summary>
        /// <returns></returns>
        public string GetRequestString()
        {
            StringBuilder sb = new StringBuilder();

            if (string.IsNullOrEmpty(APIKey))
            {
                throw new ApplicationException("APIKey was not found. Please check the configuration file or explicitly specifiy the API Key in the constructor.");
            }

            List<string> requiredParameters = new List<string>();

            foreach (string requiredParameter in RequiredParameters)
            {
                if (Parameters.Count == 0)
                {
                    requiredParameters = RequiredParameters;
                }
                else
                {
                    if (!Parameters.Keys.Contains(requiredParameter))
                    {
                        requiredParameters.Add(requiredParameter);
                    }
                }
            }

            if (requiredParameters.Count > 0)
            {
                throw new ApplicationException(MethodName + " requires these parameters: " + requiredParameters.ToDelimitedString());
            }

            if (InterfaceName == "IEconItems" && SteamGameType == SteamGameType.None)
            {
                throw new ApplicationException(InterfaceName + " requires a SteamGameType.");
            }

            string parameters = "";

            foreach (KeyValuePair<string, object> parameter in Parameters)
            {
                string key = parameter.Key;
                string value = parameter.Value.ToString().Trim().Replace(" ", string.Empty);

                parameters += string.Format("&{0}={1}", key, value.ToString());
            }

            if (SteamGameType != SteamGameType.None)
            {
                InterfaceName += "_" + (int)SteamGameType;
            }

            sb.Append(string.Format("{0}/{1}/{2}/{3}?key={4}&format={5}{6}", baseUrl, InterfaceName, MethodName, VersionCode, APIKey, SteamRequestFormat.ToString().ToLower(), parameters));

            return sb.ToString();
        }
    }
}
